home *** CD-ROM | disk | FTP | other *** search
/ HPAVC / HPAVC CD-ROM.iso / pc / ABUSESRC.ZIP / AbuseSrc / imlib / port / dos4gw / ipx.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-07-23  |  10.2 KB  |  417 lines

  1. #include "ipx.hpp"
  2. #include "jnet.hpp"
  3. #include "macs.hpp"
  4. #include "dprint.hpp"
  5. #include "system.h"
  6. #include <i86.h>
  7. #include <sys/types.h>
  8. #include <fcntl.h>
  9. #include <unistd.h>
  10. #include <stdlib.h>
  11. #include <string.h>
  12. #include <dos.h>
  13. #include "jmalloc.hpp"
  14. #include "doscall.hpp"
  15. #include "timing.hpp"
  16.  
  17. #define JC_SEG(x) (((long)x)>>4)
  18. #define JC_OFF(x) (((long)x)&0xf)
  19.  
  20. static rminfo rm;
  21.  
  22. class in_socket_dispatcher
  23. {
  24.   
  25.   ipx_in_socket **ins;
  26.   long *ports;            // ports which the in sockets are supposed to be on
  27. } ;
  28.  
  29.  
  30. int ipx_init()
  31. {
  32.   memset(&rm,0,sizeof(rm));
  33.   rm.eax=0x7a00;
  34.   RM_intr(0x2f,&rm);
  35.   return (rm.eax&0xff)==0xff;
  36. }
  37.  
  38. void ipx_uninit() { ; }
  39.  
  40. void close_ipx_socket(int fd)
  41. {
  42.   memset(&rm,0,sizeof(rm));
  43.   rm.ebx=1;
  44.   rm.edx=(ushort)bstl(fd);
  45.   RM_intr(0x7a,&rm);
  46. }
  47.  
  48.  
  49. void ipx_idle()
  50. {
  51.   memset(&rm,0,sizeof(rm));
  52.   rm.ebx=0xa;
  53.   RM_intr(0x7a,&rm); 
  54. }
  55.  
  56. uchar *ipx_get_local_address()                // same format as above (be sure to jfree this)
  57. {
  58.   uchar *addr=(uchar *)jmalloc(10,"IPX address");  // normal memory return
  59.   uchar *low_addr=(uchar *)alloc_low_memory(10);
  60.   memset(&rm,0,sizeof(rm));
  61.   rm.ebx=9;
  62.   rm.esi=JC_OFF(low_addr);
  63.   rm.es=JC_SEG(low_addr);
  64.   RM_intr(0x7a,&rm);
  65.  
  66.   memcpy(addr,low_addr,10);
  67.   free_low_memory(low_addr);
  68.   return addr;
  69. }
  70.  
  71.  
  72. void ipx_listen(ECBStructure *ecb)
  73. {
  74.   memset(&rm,0,sizeof(rm));
  75.   rm.esi=JC_OFF(ecb);
  76.   rm.es=JC_SEG(ecb);
  77.  
  78.   rm.ebx=4;
  79.   RM_intr(0x7a,&rm);
  80.  
  81.   if (rm.eax&0xff)
  82.   {
  83.     current_sock_err=SOCK_LISTEN_FAIL;
  84.     sprintf(last_sock_err,"IPX : listen failed");
  85.   }
  86. }
  87.  
  88. ipx_out_socket::ipx_out_socket(int port)
  89. {
  90.   remote_socket=-1;              // mark not connected
  91.   memset(&rm,0,sizeof(rm));
  92.   rm.ebx=0;                      // Open socket function
  93.   rm.eax=0;                      // close on program exit
  94.   rm.edx=(ushort)(bstl(port));
  95.   RM_intr(0x7a,&rm);
  96.   if (rm.eax&0xff)
  97.   {
  98.     current_sock_err=SOCK_CREATE_FAIL;
  99.     sprintf(last_sock_err,"Unable to open IPX socket\n");
  100.     return ;
  101.   }
  102.   local_socket=(ushort)bstl((rm.edx&0xffff));
  103.   printf("created socket %x\n",local_socket);
  104.  
  105.  
  106.   pk=(JC_ipx_packet *)alloc_low_memory(sizeof(JC_ipx_packet)*MAX_PACKETS);
  107.   if (!pk)
  108.   {
  109.     printf("unable to allocate low memory for packets\n");
  110.     exit(0);
  111.   }
  112.   memset(pk,0,sizeof(JC_ipx_packet)*MAX_PACKETS);
  113.  
  114.  
  115.   // setup an outgoing packet structure
  116.   pk[0].ecb.ECBSocket = (ushort)(bstl(local_socket));
  117.   pk[0].ecb.FragmentCount = 1;
  118.   pk[0].ecb.fAddress[0] = JC_OFF(&pk[0].ipx);
  119.   pk[0].ecb.fAddress[1] = JC_SEG(&pk[0].ipx);
  120. //  pk[0].ipx.PacketCheckSum=0xffff;
  121.  
  122.   uchar *my_addr=ipx_get_local_address();
  123.   memcpy(pk[0].ipx.sNetwork,my_addr,10);
  124.   pk[0].ipx.sSocket=(ushort)(bstl(local_socket));
  125.   jfree(my_addr);
  126.   
  127.   for (int i=1;i<MAX_PACKETS;i++)
  128.   {
  129.     // setup incoming packet structure
  130.     pk[i].ecb.InUseFlag = 0x1d;
  131.     pk[i].ecb.ECBSocket = (ushort)(bstl(local_socket));
  132.     pk[i].ecb.FragmentCount = 1;
  133.     pk[i].ecb.fAddress[0] = JC_OFF(&pk[i].ipx);
  134.     pk[i].ecb.fAddress[1] = JC_SEG(&pk[i].ipx);
  135.     pk[i].ecb.fSize = sizeof(JC_ipx_packet)-sizeof(ECBStructure);
  136.     ipx_listen(&pk[i].ecb);
  137.     printf("added listening ecb\n");
  138.   }  
  139.  
  140. }
  141.  
  142. int ipx_send_packet(void *packet)
  143. {
  144.   memset(&rm,0,sizeof(rm));
  145.   rm.ebx=3;                      // send packet function
  146.   rm.esi=JC_OFF(packet);
  147.   rm.es=JC_SEG(packet);
  148.   RM_intr(0x7a,&rm); 
  149.   return 1;
  150. }
  151.  
  152.  
  153. int ipx_out_socket::try_connect(char *rhost, int port)
  154. {
  155.   uchar *addr=(uchar *)name_to_address(rhost,IPX_PROTOCOL);
  156.  
  157.   printf("try connect to ");
  158.   uchar *me=addr;
  159.   for (int i=0;i<10;i++,me++)
  160.     printf("%02x:",*me);
  161.   printf("\n");
  162.  
  163.   if (addr)
  164.   {
  165.     while (pk[0].ecb.InUseFlag)                       // make sure packet is not being used!
  166.       dprintf("Packet already in use (try connect)\n");
  167.  
  168.     memcpy(&pk[0].ipx.dNetwork[0],addr,10);     // assume they are playing on the same network
  169.     memcpy(&pk[0].ecb.ImmediateAddress[0],addr+4,6);
  170.  
  171.     memset(&pk[0].ipx.dNetwork[0],0,10);
  172.  
  173.     memset(&pk[0].ipx.dNode[0],0xff,6);   
  174.     memset(&pk[0].ecb.ImmediateAddress[0],0xff,6);
  175.  
  176.     pk[0].ipx.dSocket=(ushort)bstl(port);
  177.     pk[0].verify_stamp=0xcdc;
  178.     pk[0].ipx.PacketLength=(ushort)bstl(sizeof(IPXPacketStructure)+6);
  179.  
  180.     pk[0].ecb.ECBSocket = bstl(port);
  181.     pk[0].ecb.FragmentCount = 1;
  182.     pk[0].ecb.fAddress[0] = JC_OFF(&pk[0].ipx);
  183.     pk[0].ecb.fAddress[1] = FP_SEG(&pk[0].ipx);
  184.     pk[0].ipx.PacketCheckSum=0xffff;
  185.  
  186. //    for (int j=0 ; j<4 ; j++)
  187. //      pk[0].ipx.dNetwork[j] = localadr.network[j];
  188.     pk[0].ipx.dSocket = bstl(port);
  189.     
  190.  
  191.     jfree(addr);
  192.     int found_reply=-1;
  193.     for (int tries=0;found_reply==-1 && tries<10;tries++)
  194.     {
  195.       ipx_send_packet(&pk[0].ecb);
  196.       printf("sent request packet\n");
  197.       ipx_idle();
  198.       milli_wait(500);           // wait 1/2 second for a response
  199.       for (int i=1;i<MAX_PACKETS;i++)
  200.       {
  201.     if (!pk[i].ecb.InUseFlag && pk[i].verify_stamp==0xcdc)
  202.     {
  203.       if (found_reply!=-1)    // we found two replies, this shouldn't happen
  204.       {
  205.         dprintf("Two replies found for connection request, what's going on?\n");
  206.         found_reply=-1;
  207.         tries=10;
  208.       }
  209.       found_reply=i;
  210.       printf("found reply on packet %d\n",i);
  211.     }
  212.       }
  213.     }
  214.  
  215.  
  216.     if (found_reply==-1)
  217.       return 0;
  218.     else 
  219.     { 
  220.       remote_socket=pk[found_reply].time_stamp;
  221.       local_time=remote_time=0;
  222.       pk[0].ipx.dSocket=(ushort)bstl(remote_socket);
  223.       return 1;
  224.     }
  225.   } else dprintf("Unable to get an IPX address for hostname '%s'\n",rhost);
  226.   return 0;
  227. }
  228.  
  229. int ipx_out_socket::ready_to_read()
  230. {
  231.   if (remote_socket==-1)  return 1;  // not connected, return true so program doesn't block for a
  232.                                      // packet that will never come
  233.  
  234.   for (int i=1;i<MAX_PACKETS;i++)
  235.   {
  236.     if (!pk[i].ecb.InUseFlag && pk[i].verify_stamp==0xcdc)
  237.       return 1;
  238.   } 
  239.   return 0;
  240. }
  241.  
  242.  
  243. int ipx_out_socket::ready_to_write()            // true if send packet is clear
  244. {
  245.   return pk[0].ecb.InUseFlag==0;
  246. }
  247.  
  248.  
  249.  
  250. int ipx_out_socket::send(packet &pak)
  251. {
  252.   if (remote_socket==-1) return 0;  // not connected, cannot send packet
  253.  
  254.   ushort size=lstl(pak.wo-2);        // attach the packet size to the front of the packet
  255.   memcpy(pak.buf,&size,2);
  256.   
  257.  
  258.   int bytes_to_write=size+2;
  259.   uchar *pk_off=pak.buf;
  260.   while (bytes_to_write)           // break the packet up into 512 byte segments and send till through
  261.   {
  262.     while (!ready_to_write()) ;       // wait till last packet finishes
  263.  
  264.     int size_to_send=bytes_to_write>512 ? 512 : bytes_to_write;
  265.  
  266.     memcpy(pk[0].buffer,pk_off,size_to_send);
  267.     pk[0].time_stamp=local_time;
  268.     local_time++;
  269.     pk[0].verify_stamp=0xcdc;
  270.     pk[0].ipx.PacketLength=(ushort)bstl(sizeof(IPXPacketStructure)+6+size_to_send);
  271.  
  272.     ipx_send_packet(&pk[0]);
  273.     
  274.     pk_off+=size_to_send;
  275.     bytes_to_write-=size_to_send;
  276.   }
  277.  
  278.   return 1;
  279. }
  280.  
  281.  
  282. int ipx_out_socket::get(packet &pak)
  283. {
  284.   pak.ro=pak.wo=2;
  285.   int start=-1;
  286.   time_marker then;
  287.   do
  288.   {
  289.     for (int i=1;start==-1 && i<MAX_PACKETS;i++)
  290.       if (!pk[i].ecb.InUseFlag && pk[i].time_stamp==remote_time && pk[i].verify_stamp==0xcdc)
  291.         start=i;
  292.     time_marker now;
  293.  
  294.     if (now.diff_time(&then)>20)  // twenty second timeout
  295.       return 0;
  296.  
  297.   } while (start==-1);     // wait until we get the packet we are looking for
  298.  
  299.   remote_time++;
  300.  
  301.   long data_size=pk[start].ipx.PacketLength-sizeof(IPXPacketStructure)-6;
  302.  
  303.   if (data_size<2)   // even enough space to read packet size?
  304.     return 0;
  305.  
  306.   ushort size;
  307.   memcpy(&size,pk[start].buffer,2);
  308.   data_size-=2;
  309.  
  310.   size=lstl(size);  
  311.   pak.rend=size+2;
  312.   pak.make_bigger(pak.rend);
  313.  
  314.   uchar *buf=pak.buf+2;
  315.   uchar *source=pk[start].buffer+2;
  316.  
  317.   int bytes_left=size;
  318.   do
  319.   {
  320.     memcpy(buf,source,data_size);
  321.     buf+=data_size;
  322.     bytes_left-=data_size;
  323.     ipx_listen(&pk[start].ecb);    // this packet is done and available for listening again
  324.     pk[start].ecb.InUseFlag = 0x1d;
  325.  
  326.     if (bytes_left)              // see if we need to get more packets
  327.     {
  328.       time_marker then;
  329.       do
  330.       {
  331.     for (int i=1;start==-1 && i<MAX_PACKETS;i++)
  332.           if (pk[i].time_stamp==remote_time && pk[i].verify_stamp==0xcdc)
  333.         start=i;
  334.     time_marker now;
  335.  
  336.     if (now.diff_time(&then)>20)  // twenty second timeout
  337.           return 0;
  338.       } while (start==-1);     // wait until we get the packet we are looking for
  339.  
  340.       remote_time++;
  341.       source=pk[start].buffer;
  342.       data_size=pk[start].ipx.PacketLength-sizeof(IPXPacketStructure)-6;
  343.     }
  344.   } while (bytes_left>0);
  345.  
  346.   return 1;
  347. }
  348.  
  349.  
  350. ipx_out_socket::~ipx_out_socket()
  351.   close_ipx_socket(local_socket);
  352.   free_low_memory(pk);
  353. }
  354.  
  355. ipx_in_socket::ipx_in_socket(int Port)
  356. {
  357.   port=Port;
  358.   listener=new ipx_out_socket(port);
  359. }
  360.  
  361. out_socket *ipx_in_socket::check_for_connect()
  362. {
  363.   int start=-1;
  364.   ipx_idle();
  365.   for (int i=1;i<MAX_PACKETS;i++)
  366.   {
  367.     for (int i=1;start==-1 && i<MAX_PACKETS;i++)
  368.       if (!listener->pk[i].ecb.InUseFlag)
  369.       {
  370.     printf("found a connection\n");
  371.     if (listener->pk[i].verify_stamp==0xcdc)      
  372.           start=i;
  373.     else 
  374.     {
  375.       listener->pk[i].ecb.InUseFlag=0x1d;
  376.       ipx_listen(&listener->pk[i].ecb);  // this packet is done and available for listening again
  377.  
  378.       printf("bad stamp, getting packets from someone else!\n");
  379.     }
  380.       }
  381.   }
  382.  
  383.   if (start!=-1)
  384.   {
  385.     ipx_out_socket *nsock=new ipx_out_socket(0);  // create a new socket and dynamicly allocate port
  386.     listener->pk[0].verify_stamp=0xcdc;
  387.     listener->pk[0].ipx.PacketLength=sizeof(IPXPacketStructure)+6;
  388.     listener->pk[0].time_stamp=nsock->local_socket;
  389.  
  390.     uchar tmp_addr[10];
  391.     memcpy(tmp_addr,listener->pk[0].ipx.dNetwork,10);    
  392.     memcpy(listener->pk[0].ipx.dNetwork,
  393.        listener->pk[start].ipx.sNetwork,12);  // source <- dest
  394.     memcpy(listener->pk[start].ipx.sNetwork,tmp_addr,10);  // dest <- source
  395.  
  396.     ipx_listen(&listener->pk[start].ecb);    // this packet is done and available for listening again
  397.     listener->pk[start].ecb.InUseFlag = 0x1d;
  398.     
  399.     ipx_send_packet(&listener->pk[0]);        // send new port info back to caller
  400.     return nsock;
  401.   }
  402.   return NULL;
  403. }
  404.  
  405.  
  406.  
  407. ipx_in_socket::~ipx_in_socket()
  408. {
  409.   delete listener;
  410. }
  411.  
  412.  
  413.  
  414.  
  415.  
  416.